Mise à jour le 13/11/2021
Utilisation des exceptions en PHP

Utilisation des exceptions en PHP

Voici une interprétation de la page 15 Best Practices for Exception Handling(http://codebuild.blogspot.com/2012/01/15-best-practices-about-exception.html). Certaines best practices se complètent, il ne me semble pas nécessaire d'en citer 15.

1. Ne pas utiliser les exceptions pour gérer des erreurs métiers

Toutes les erreurs métiers doivent être prévues et gérées via des conditions classiques, on évitera donc d'écrire quelque chose comme catch (FunctionalException $e).

2. Eviter l'usage du \Exception

Le nom de l'exception doit être clair, on évite d'utiliser la classe \Exception, trop générale. Donc on évite le catch (\Exception $e) même dans le cas où on utiliserait une librairie/composant qui retournerait beaucoup d'exception (ex: Doctrine).
Evidemment, si la librairie retourne une instance d'\Exception, il n'y a pas le choix que de la catcher.cher

2.1 Exemples de noms clairs

* MysqlConnectionException
* NullEntityException
* EmptyFileException
* DeniedAccessException
* HttpException (Eventuellement, on peut définir des exceptions pour chaque code d'erreur HTTP)
En plus d'avoir un nom clair, chaque exception doit être correctement documentée.

3. Ne pas utiliser autre chose que des exceptions en cas d'erreurs techniques

On évite de retourner des nombres négatifs par exemple selon les erreurs. Mieux vaut privilégier des exceptions claires et non ambigues.

3.1 Exemples de mapping pour une lecture de fichier

* -1 -> FileNotFoundException
* -2 -> FileNotReadableException
* -3 -> UnsupportedFileException
* -4 -> TooBigFileException (dans le cas d'une limite à l'écriture par exemple)

4. Eviter de faire uniquement un throw dans un catch

Alors, ce genre de code est inutile :

try {
    // Peu importe
} catch (AnyException $e) {
    throw $e;
}

Soit le catch sert à quelque chose (on logguerait l'erreur par exemple), soit s'il ne sert à rien, il n'a pas de raison d'être.
De la même façon, ce n'est pas pertinent non plus de transformer le type d'exception en un autre type d'exception, autant laisser passer l'exception d'origine.
Eventuellement, il peut être par contre intéressant de compléter le message d'erreur de l'exception afin d'aider à la résolution du problème.

4.1 Eviter de ne rien faire dans le catch

Alors, ignorer l'exception, c'est souvent une fausse bonne idée. On évitera donc ce code :

try {
    // Peu importe
} catch (AnyException $e) {
    // Sifflote
}

5. Faire de l'héritage autant que faire ce peut

Plutôt que de faire hériter toutes ses exceptions avec \Exception, cela peut être intéressant de les réunir au sein de leurs domaines respectifs (ex: FileNotFoundException extends FileException, NotFoundHttpException extends HttpException, UnauthorizedUserException extends UserException...).

6. Logger les exceptions selon leur gravité

Selon les exceptions catchés, il peut être intéressant d'inscrire dans les logs les erreurs en fonction de leur gravité (DEBUG/NOTICE/FATAL).
On évite par contre de logger plusieurs fois la même erreur.

6.1 Exemples de niveau

DEBUG : Fichier non initialisé, Utilisateur n'existant pas encore
NOTICE : Time out sur la récupération d'une donnée non essentielle en cache par exemple
FATAL : erreur de connexion à la BDD, moteur de recherche, file d'attente

7. Utiliser le finally

Rarement utilisé, il peut être parfois être pratique pour libérer des ressources par exemple.

8. Eviter les try/catch dans des boucles

On peut catcher 1 fois mille erreurs plutôt que catcher mille fois 1 erreur.

9. Faire plusieurs try/catch plutôt qu'un seul

Bon cela se défend car personnellement je préfère fois un seul try/catch que plusieurs d'affilée.
L'idée est qu'il y ait peu d'instructions dans le try afin d'évaluer plus facilement d'où proviennent les erreurs.

10. User de code d'erreurs

Dans l'idéal, chaque exception est accompagnée d'un code d'erreur qui simplifiera la maintenance de l'application, ne serait-ce que dans l'étude statistique des problèmes courants.

11. Enfin, ne pas en abuser

Si pour afficher une seule page web, on risque de tomber sur l'une des 200 exceptions possibles, c'est que manifestement, la page est peut-être trop complexe.
Au-delà de 10 exceptions possibles pour un seul appel HTTP, je pense que cela devient ingérable.